package com.momei.security.handler;

import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.momei.exception.BaseException;
import com.momei.security.MyUserDetails;
import com.momei.util.JwtTokenUtil;
import com.momei.util.RedisUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

/**
 *@description: token过滤器 验证token有效性
 *@author: momo
 *@time: 2020/9/11
 */
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
{
    private static final Logger LOGGER = LoggerFactory.getLogger(JwtAuthenticationTokenFilter.class);

    private final static String HEADER = "X-Token";

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private RedisUtils redisUtils;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        String headerToken = request.getHeader(HEADER);

        if (StringUtils.isNotBlank(headerToken))
        {
            boolean check = false;
            // 通过令牌获取用户名称
            String usercode = jwtTokenUtil.getUsercodeFromToken(headerToken);
            try {
                check = redisUtils.isTokenExpired(usercode);
            } catch (Exception e) {
                throw new BaseException("令牌已过期，请重新登录! ");
            }
            if (!check){
                // 判断用户不为空，且SecurityContextHolder授权信息还是空的
                if (usercode != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                    MyUserDetails userDetails = (MyUserDetails) userDetailsService.loadUserByUsername(usercode);
                    // 验证令牌有效性
                    boolean validata = false;
                    try {
                        // todo: redis中校验token有效性
                        validata = jwtTokenUtil.validateToken(headerToken, userDetails);
                    }catch (Exception e) {
                        throw new BaseException("验证token无效! ");
                    }
                    if (validata) {
                        UsernamePasswordAuthenticationToken authentication =
                                new UsernamePasswordAuthenticationToken(
                                        userDetails,
                                        null,
                                        userDetails.getAuthorities()
                                );
                        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                        // 将 authentication 存入 ThreadLocal
                        SecurityContextHolder.getContext().setAuthentication(authentication);
                    }
                }
            }
        }
        filterChain.doFilter(request, response);
    }
}
